/*
** proc_event.c for pud in mrcellophane/libpud
** 
** Made by solomon hykes
** Login   <torgau@gmail.com>
** 
** Started on  Mon May 16 17:30:02 2005 solomon hykes
** Last update Mon Jul 11 00:00:52 2005 solomon hykes
*/

#include <errno.h>
#include "pud_sys.h"

void		pud_print_event(pud_process *p, pud_event *ev)
{
  char		*what;

  printf("[%d] ", p->pid);
  if (ev->what == ev_stopped)
    printf("*** Stopped by signal [%02d]", ev->data.signal);
  else if (ev->what == ev_signaled)
    printf("*** Killed by signal  [%02d]", ev->data.signal);
  else if (ev->what == ev_exited)
    printf("*** Exit(%02d)            ", ev->data.exitcode);
  else if (ev->what == ev_trapped)
    printf("*** Trapped               ");
  else
    printf("*** Unknown event         ");

  if ((ev->what == ev_stopped) || (ev->what == ev_trapped))
    {
      sys_pud_process	*proc = (sys_pud_process *)p;
      long		*sample;
      int		i;
      #define SAMPLE_WORDS	8

      printf(" pc=%08.8p", proc->pc);

      printf(" stackp=%08.8p [ ", proc->stackp);
      sample = malloc(SAMPLE_WORDS * sizeof(long));
      if (pud_mem_read(p, proc->stackp, (void *)sample, SAMPLE_WORDS * sizeof(long)) == -1)
	printf("...Error fetching data at %8.8p...", proc->stackp);
      else
	for (i = 0; i < SAMPLE_WORDS; i++)
	  printf("%08.8p ", sample[i]);
      printf("]\n");
    }
  else
    printf("\n");
}

pud_event	*pud_next_event(pud_process *p)
{
  sys_pud_process	*proc = (sys_pud_process *)p;
  int			status;

  while (waitpid(proc->pid, &status, 0) < 0)
    if (errno != EINTR)
      return (NULL);
    /* If the process was stopped */
  proc->event.pass_signal = 0;
  if (WIFSTOPPED(status))
    {
      int	sig;

      /* Set status */
      proc->status = status_stopped;
      /* Update regs */
      if (sys_pud_getregs(proc) == ret_err)
	return (NULL);
      
      if ((sig = WSTOPSIG(status)) == SIGTRAP)
	{
	  proc->event.what = ev_trapped;
	  proc->event.data.where = proc->pc;
	}
      else
	{
	  proc->event.what = ev_stopped;
	  proc->event.data.signal = WSTOPSIG(status);
	  proc->event.pass_signal = proc->event.data.signal;
	}
    }
  else
    {
      if (WIFSIGNALED(status))
	{
	  proc->status = status_dead;
	  proc->event.what = ev_signaled;
	  proc->event.data.signal = WTERMSIG(status);
	}
      else if (WIFEXITED(status))
	{
	  proc->status = status_dead;
	  proc->event.what = ev_exited;
	  proc->event.data.exitcode = WEXITSTATUS(status);
	}
    }
  proc->event_count++;
  return (&proc->event);
}

pud_event	*pud_last_event(pud_process *p)
{
  sys_pud_process	*proc = (sys_pud_process *)p;

  if (proc->event_count == 0)
    return (NULL);
  return (&proc->event);
}
